use serde::{Serialize, Serializer};
use std::{collections::HashMap, sync::Mutex};
use tauri::Manager;
use tauri::{command, AppHandle, Runtime, State, Window};

use model_graph_types::{
    connector::{Connector, ExecuteOptions, QueryOptions},
    database::{DataSource, DatabaseType},
    modeling::Value,
};
use serde_json::Value as JsonValue;
use union_connector::UnionConnector;

use model_graph_common::{transport::http::http_download_file, utils::zip::extract_v8_to_fs};

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error(transparent)]
    Anyhow(#[from] anyhow::Error),
}

impl Serialize for Error {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.to_string().as_ref())
    }
}

type Result<T> = std::result::Result<T, Error>;

#[derive(Default)]
pub struct ContextState(Mutex<HashMap<String, UnionConnector>>);

#[command]
pub async fn local_install<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    icon: String,
    file: String,
) -> Result<bool> {
    let icon_path = "";
    let pkg_path = "";
    //下载文件
    let _ = http_download_file(&icon, icon_path).await?;
    let _ = http_download_file(&file, pkg_path).await?;
    //解压文件
    let target_path = "";
    //读取解压文件内容
    let zip_file: Vec<u8> = vec![];

    extract_v8_to_fs(&zip_file, target_path)?;
    Ok(true)
}

#[command]
pub async fn install<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    plugin: String,
) -> Result<bool> {
    Ok(true)
}

#[command]
pub async fn uninstall<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    plugin: String,
) -> Result<bool> {
    Ok(true)
}

#[command]
pub async fn upgrade<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    plugin: String,
) -> Result<(Vec<JsonValue>, Vec<JsonValue>)> {
    Err(Error::Anyhow(anyhow::anyhow!("upgrade")))
}

#[command]
pub async fn infor<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    plugin: String,
) -> Result<String> {
    Err(Error::Anyhow(anyhow::anyhow!("infor")))
}

#[command]
pub async fn wasms<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    plugin: String,
) -> Result<String> {
    Err(Error::Anyhow(anyhow::anyhow!("wasms")))
}

#[tauri::command]
pub fn eval<R: Runtime>(self_window: Window<R>, window: String, script: String) -> (i32, String) {
    let target_window_option = self_window.get_webview(window.as_str());

    match target_window_option {
        Some(win) => {
            tracing::debug!("window:{},script:{}", window, script);
            let _ = win.eval(format!("{}", script).as_str());
            (0, String::from("成功"))
        }
        None => (1, String::from("没有找到Window!")),
    }
}

#[tauri::command]
pub fn window_set_url<R: Runtime>(self_window: Window<R>, url: String) -> (i32, String) {
    let target_window_option = self_window.get_webview(self_window.label());
    match target_window_option {
        Some(win) => {
            tracing::debug!("url:{}", url);
            let _ = win.eval(format!("window.location.replace('{}')", url).as_str());
            (0, String::from("成功"))
        }
        None => (1, String::from("没有找到Window!")),
    }
}
